package table

import (
	"context"
	"errors"
	"fmt"
	form "pd/server/app/pd/form/order"
	model "pd/server/app/pd/model/order"
	"pd/server/com/db"
	"pd/server/plugin/logger"
	"time"
)

type OrderTable struct {
}

func (this *OrderTable) Create(ctx context.Context, frm *form.CreateOrderForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	sess := conn.Conn.NewSession().Context(ctx)
	if err = sess.Begin(); err != nil {
		return
	}
	defer func() {
		if err == nil {
			err = sess.Commit()
		}
		if err != nil {
			sess.Rollback()
		}
	}()

	if _, err = sess.InsertOne(frm.OrderModel); err != nil {
		return
	}
	for _, item := range frm.Products {
		item.OrderId = frm.Id
	}
	if _, err = sess.Insert(frm.Products); err != nil {
		return
	}
	return
}

func (this *OrderTable) Update(ctx context.Context, frm *form.CreateOrderForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	sess := conn.Conn.NewSession().Context(ctx)
	if err = sess.Begin(); err != nil {
		return
	}
	defer func() {
		if err == nil {
			err = sess.Commit()
		}
		if err != nil {
			sess.Rollback()
		}
	}()

	frm.LastUpdateTime = time.Now()
	affected, err := sess.Where("id = ? and merchant_id = ?", frm.Id, frm.MerchantId).
		Omit("id", "merchant_id", "order_no", "create_time").
		Update(frm.OrderModel)
	if err != nil {
		logger.Error(err)
		return
	}
	if affected != 1 {
		err = errors.New("更新失败")
		return
	}
	var items []*model.OrderItemsModel
	if err = sess.Where("order_id = ?", frm.Id).Select("*").Find(&items); err != nil {
		return
	}

	var found bool
	for _, item1 := range items {
		found = false
		for _, item2 := range frm.Products {
			if item1.ProductId == item2.ProductId {
				found = true
				if item1.Price != item2.Price || item1.ProductCount != item2.ProductCount {
					if _, err = sess.Where("id = ?", item1.Id).Cols("price", "product_count").Update(item2); err != nil {
						return
					}
				}
				break
			}
		}
		if !found {
			if _, err = sess.Where("id = ?", item1.Id).Delete(&model.OrderItemsModel{}); err != nil {
				return
			}
		}
	}
	for _, item2 := range frm.Products {
		found = false
		for _, item1 := range items {
			if item1.ProductId == item2.ProductId {
				found = true
				break
			}
		}
		if !found {
			item2.OrderId = frm.Id
			if _, err = sess.InsertOne(item2); err != nil {
				return
			}
		}
	}
	return
}

func (this *OrderTable) OrderList(ctx context.Context, frm *form.OrderListForm) (orderList []*model.OrderNode, total int64, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)

	q.Where("merchant_id = ?", frm.MerchantId)
	if frm.DeliveryPerson != "" {
		q.Where("delivery_person_id in (select id from user where real_name like ?)", fmt.Sprintf("%%%s%%", frm.DeliveryPerson))
	}
	if frm.Keyword != "" {
		tmp := fmt.Sprintf("%%%s%%", frm.Keyword)
		q.Where("address like ? or nickname like ?", tmp, tmp)
	}
	if frm.PhoneNumber != "" {
		q.Where("phone_number = ?", frm.PhoneNumber)
	}
	if frm.Source != "" {
		q.Where("source = ?", frm.Source)
	}
	if frm.Status != "" {
		q.Where("status = ?", frm.Status)
	}
	if frm.Current > 0 {
		q.Limit(frm.Size, (frm.Current-1)*frm.Size)
	} else {
		q.Limit(200)
	}
	q.Desc("id")
	q.Select("*")
	if total, err = q.FindAndCount(&orderList); err != nil {
		return
	}
	orderIds := make([]int64, 0, len(orderList))
	for _, order := range orderList {
		orderIds = append(orderIds, order.Id)
	}
	var items []*model.OrderItemNode
	if err = q.In("order_id", orderIds).
		Select("*").
		Find(&items); err != nil {
		return
	}
	for _, item := range items {
		for _, order := range orderList {
			if item.OrderId == order.Id {
				order.Products = append(order.Products, item)
				break
			}
		}
	}

	return
}

func (this *OrderTable) Delete(ctx context.Context, frm *model.OrderModel) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	sess := conn.Conn.NewSession().Context(ctx)
	if err = sess.Begin(); err != nil {
		return
	}
	defer func() {
		if err == nil {
			err = sess.Commit()
		}
		if err != nil {
			sess.Rollback()
		}
	}()

	var affected int64
	if affected, err = sess.Where("id = ? and merchant_id = ?", frm.Id, frm.MerchantId).Delete(&model.OrderModel{}); err != nil {
		return
	} else if affected != 1 {
		err = errors.New("订单不存在")
		return
	}
	if _, err = sess.Where("order_id = ?", frm.Id).Delete(&model.OrderItemsModel{}); err != nil {
		return
	}
	return
}
